iT邦幫忙

2022 iThome 鐵人賽

DAY 26
0
Software Development

30天成為鍵盤麥可貝:前端視覺特效開發實戰系列 第 26

Day26: WebGL Shader—透過Shader製作光暈:速成篇

  • 分享至 

  • xImage
  •  

下面我將介紹如何透過Shader製作一個光暈。

分三個階段:

  1. 用three.js製作Shader材質
  2. 在vertex shader加上vertexNormal
  3. 在fragment shader加上「神秘的程式碼」

準備程式碼

CodePen

我已經準備好範本程式碼。如果看到畫面是淡藍色,那代表這是正常顯示的範本。

https://ithelp.ithome.com.tw/upload/images/20221016/20142505ZiQYyhHC3V.png

https://codepen.io/umas-sunavan/pen/gOzEqwa?editors=1010

用three.js製作Shader材質

我們建立一個球體。球體的材質是由ShaderMaterial組成。而ShaderMaterial所使用的Shader程式碼,來自HTML。

+const addSphere = () => {
+	const vertex = document.getElementById('vertexShader').innerHTML
+	const fragment = document.getElementById('fragmentShader').innerHTML
+    const geo = new THREE.SphereGeometry(5,50,50)
+    const mat = new THREE.ShaderMaterial({
+		vertexShader: vertex,
+		fragmentShader: fragment,
+	})
+    const mesh = new THREE.Mesh(geo, mat)
+    scene.add(mesh)
+    return mesh
+}

+addSphere()

HTML:

+<div style="display: none">
+    <p id="fragmentShader">
+        #ifdef GL_ES
+        precision mediump float;
+        #endif
+        void main(void){
+					gl_FragColor=vec4(0.,0.,0.2,1.);
+        }
+    </p>
+    <p id="vertexShader">
+        void main(void){gl_Position=projectionMatrix*modelViewMatrix*vec4(position, 1.0);
+        }
+    </p>
+</div>

https://ithelp.ithome.com.tw/upload/images/20221016/20142505oOJTkhQMCi.png

在vertex shader加上vertexNormal

  • 在vertex shader我們添加vertexNormalvertexNormal 是我們即將從vertex shader傳入到fragment shader的變數,而normal則是three.js提供的變數。

    +varying vec3 vertexNormal;
    
    void main(void){
    +  vertexNormal = normal;
    	void main(void){gl_Position=projectionMatrix*modelViewMatrix*vec4(position, 1.0);
    }
    
  • 在fragment shader我們添加。

    	#ifdef GL_ES
    	precision mediump float;
    	#endif
    
    +	varying vec3 vertexNormal;
    	void main(void){
    		gl_FragColor=vec4(0.,0.,0.2,1.);
    	}
    

在fragment shader加上「神秘的程式碼」

過去我們有介紹過fragment shader,gl_FragColor會是每個像素最終的顏色。如果我們設置成vec4(0.2,0.2,0.4,1.),那大概長這樣:

https://ithelp.ithome.com.tw/upload/images/20221016/20142505JdMJrzzPnL.png

我們加上「神秘的程式碼」:

	varying vec3 vertexNormal;
	void main(void){
+		float intensity = 1.05 - dot(vertexNormal, vec3(0.,0.,1.));
+		vec3 atmosphere = vec3(.3, .6, 1.) * intensity;
+		gl_FragColor=vec4(atmosphere,0.) + vec4(0.,0.,0.2,1.);
-		gl_FragColor=vec4(0.,0.,0.2,1.);
	}

如此一來,光暈就完成了。

完成品

https://ithelp.ithome.com.tw/upload/images/20221016/20142505yU0DVyvMAk.png

CodePen

https://ithelp.ithome.com.tw/upload/images/20221016/20142505fgJB1fEeit.png

https://codepen.io/umas-sunavan/pen/KKREJzq

小結

你現在可能會充滿問號,對於為什麼可以形成光暈有滿滿的問號。

不過沒關係,我們接下來將用兩篇的篇幅解釋為什麼光暈可以生成。並且透過這個案例,不斷挖掘shader的原理,最後完整的釐清光暈的運作方式。

前兩篇,我們先講解原理,再討論實作方式。這樣的作法非常教科書。很多時候我們在Shader研究原理時,順序往往是倒過來的。意思是:我們常常會先看到一個很好的Shader程式碼,但不知道其原理,不斷推敲回去。

所以從本篇開始,我會從程式碼去推敲其作用,並且延伸其作用的概念,最後講解整個原理。

參考資料

經典大作Book of shader的說明

GLSL提供的函式

WebGLProgram的說明


上一篇
Day: 25 使用Shader創造漸層
下一篇
Day27: WebGL Shader—透過Shader製作光暈:Shader傳值的原理
系列文
30天成為鍵盤麥可貝:前端視覺特效開發實戰31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言